﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.Diagnostics;
using System.Collections.Concurrent;

namespace Xfs
{
    ///TCP异步通信，Iocp架构，Socket异步,SocketAsyncEventArgs类。
    public abstract class XfsNetSocketComponent : XfsEntity
    {
        #region Properties 
        public abstract bool IsOuter { get; }                                                          /// 内外网？
        public bool IsRunning { get; set; }                                                             /// 服务器是否正在运行
        public XfsSenceType SenceType { get; set; }                                                      /// 服务器类型？
        public bool IsServer
        {
            get
            {
                if (this.SenceType == XfsSenceType.XfsClient)
                {
                    return false;
                }
                return true;
            }
          }                                                                          /// 服务端？客户端？
        public IXfsMessageDispatcher? MessageDispatcher { get; set; }                                  /// 内外网消息分捡器？
        private Socket _netSocket { get; set; }                                                         /// 服务器是否正在运行      
        private bool disposed { get; set; } = false;                                                     /// 是否解放
        private IPEndPoint _ipEendPoint { get; set; }                                                   /// 监听的IP地址
        private int _port { get; set; } = 4002;                                                         /// 监听的端口
        private string _address { get; set; } = "127.0.0.1";
        private int _maxSeverSessiong { get; set; } = 10;                                               /// 服务器程序允许的最大客户端连接数
        
        public XfsSessionPoolComponent SessionPool
         {
            get
            {
                if (this.GetComponent<XfsSessionPoolComponent>() == null)
                {
                    this.AddComponent<XfsSessionPoolComponent>();
                }                
                return this.GetComponent<XfsSessionPoolComponent>();
            }
        }                                                     /// 会话对象池

        public readonly Dictionary<long, XfsSession> Sessions = new Dictionary<long, XfsSession>();                     /// 活跃的会话群
        public readonly Dictionary<IPEndPoint, XfsSession> AdressSessions = new Dictionary<IPEndPoint, XfsSession>();       /// 活跃的会话群
        public readonly Queue<Socket> WaitingSockets = new Queue<Socket>();
        #endregion

        #region ArgsInit
        public XfsNetSocketComponent() { }
       
        /// 初始化函数        
        public void ArgsInit(string address,int port,int maxClient)
        {
            this._address = address;
            this._port = port;
            this._maxSeverSessiong = maxClient;

            this.ArgsInit();
        }
        public void ArgsInit()
        {
            if (this._ipEendPoint == null)
            {
                this._ipEendPoint = new IPEndPoint(IPAddress.Parse(this._address), this._port) as IPEndPoint;
            }
        }
        #endregion

        #region Server ///启动监听
        /// Server启动 监听
        public void ServerListenStart()
        {
            if (!this.IsRunning)
            {
                this._netSocket = new Socket(_ipEendPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);// 创建监听socket
                this._netSocket.Bind(_ipEendPoint);
                this._netSocket.Listen(this._maxSeverSessiong); // 开始监听
                this.IsRunning = true;

                Console.WriteLine(XfsTimeHelper.CurrentTime() + " 93. 开始监听: " + " XfsNetSocketComponent.");
                Console.WriteLine(XfsTimeHelper.CurrentTime() + " 94. L: " + this._netSocket.LocalEndPoint);
                Console.WriteLine(XfsTimeHelper.CurrentTime() + " 95. R: " + this._netSocket.RemoteEndPoint);

                // 在监听Socket上投递一个接受请求。
                this.StartAccept(null);
            }
        }
        /// Server从客户端开始接受一个连接操作
        private void StartAccept(SocketAsyncEventArgs e)
        {
            if (e == null)
            {
                e = new SocketAsyncEventArgs();

                //e.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted);和下一行作用相同
                e.Completed += (sender, e) => this.ProcessAccept(e); ///和上一行作用相同

                Console.WriteLine(XfsTimeHelper.CurrentTime() + " 79. e.LastOperation: " + e.LastOperation.ToString());
            }
            else
            {
                e.AcceptSocket = null;
            }

            //_maxAcceptedClients.WaitOne();

            if (!this._netSocket.AcceptAsync(e))
            {
                Console.WriteLine(XfsTimeHelper.CurrentTime() + " 91. e.LastOperation: " + e.LastOperation.ToString());

                this.ProcessAccept(e);
                //如果I/O挂起等待异步则触发AcceptAsyn_Asyn_Completed事件
                //此时I/O操作同步完成，不会触发Asyn_Completed事件，所以指定BeginAccept()方法
            }
        }
        /// Server监听Socket接受处理
        private void ProcessAccept(SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {
                Socket? peerSocket = e.AcceptSocket;//和客户端关联的socket
                if (peerSocket.Connected)
                {
                    try
                    {
                        ///限制监听数量
                        if (this.Sessions.Count >= this._maxSeverSessiong)
                        {
                            ///触发事件///在线排队等待
                            this.WaitingSockets.Enqueue(peerSocket);

                            Console.WriteLine(XfsTimeHelper.CurrentTime() + " " + this.GetType().Name + " 118. 客户端排队列表 "  + this.WaitingSockets.Count + " 位.");

                            return;
                        }

                        ///用一个会话Session接收socket
                        this.SessionReceiveAsync(peerSocket, true);
                    }
                    catch (SocketException ex)
                    {
                        Console.WriteLine(XfsTimeHelper.CurrentTime() + String.Format(" 127. 接收客户 {0} 数据出错, 异常信息： {1} 。", this._ipEendPoint, ex.ToString()));
                        //TODO 异常处理
                    }

                    //投递下一个接受请求
                    this.StartAccept(e);
                }
            }
        }
        #endregion

        #region Client ///开始连接
        /// 启动连结
        public void ClientConnentStart()
        {
            if (!this.IsRunning)
            {
                this._netSocket = new Socket(this._ipEendPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);// 创建监听socket
                this._netSocket.ConnectAsync(this._ipEendPoint);
            
                this.IsRunning = true;

                ///用一个会话Session接收socket
                this.SessionReceiveAsync(this._netSocket, false);               
            }
        }
        #endregion

        #region Server Client 共用 Add Remove    
        private void SessionReceiveAsync(Socket socket ,bool isServer)
        {
            XfsSession? session = SessionPool.Pop(this);
            if (session == null) return;
            
            ///加入会话字典
            this.Add(session);

            ///如果是客户端，将会话给客户端内网Client
            if (!isServer && XfsGame.XfsSence.GetComponent<XfsNetInnerComponent>() != null)
            {
                XfsGame.XfsSence.GetComponent<XfsNetInnerComponent>().Client = session;
            }

            session.ReceiveAsync(socket);
        }

        public XfsSession? Get(long instanceid)
        {
            if (this.Sessions.TryGetValue(instanceid, out XfsSession? ses))
            {
                return ses;
            }
            return null;
        }

        private void Add(XfsSession session)
        {
            if (this.Sessions.TryGetValue(session.InstanceId, out XfsSession? ses))
            {
                this.Sessions.Remove(ses.InstanceId);
            }
            this.Sessions.Add(session.InstanceId, session);

            this.UseWhrite();
        }

        public void Remove(XfsSession session)
        {
            ///从会话列表中移除
            this.Sessions.Remove(session.InstanceId);

            ///回收到Session池里
            this.SessionPool.Push(session);

            ///如果是客户端，修改客户端的状态为没运行，没连结，然后客户端会自动自动重连
            if (!this.IsServer && this.IsOuter)
            {
                this.IsRunning = false;
            }

            this.CloseWhrite();
        }

        public void UseWhrite()
        {
            Console.WriteLine(XfsTimeHelper.CurrentTime() + " 一个Session : 开始连接 总数: " + this.Sessions.Count);
            Console.WriteLine(XfsTimeHelper.CurrentTime() + " 一个Session : 会话池子 余量: " + this.SessionPool.Count);
        }
      
        public void CloseWhrite()
        {
            Console.WriteLine(XfsTimeHelper.CurrentTime() + " 一个Session : 中断连接 余数: " + this.Sessions.Count);
            Console.WriteLine(XfsTimeHelper.CurrentTime() + " 一个Session : 会话池子 总量: " + this.SessionPool.Count);
        }
        #endregion

        #region Dispose
        public override void Dispose()
        {
            if (!this.disposed)
            {
                try
                {
                    this.IsRunning = false;
                    if (this._netSocket != null)
                    {
                        this._netSocket = null;
                    }
                }
                catch (SocketException ex)
                {
                    //TODO 事件
                }
                this.disposed = true;
            }
            GC.SuppressFinalize(this);
        }
        #endregion
    }

    public class MessageData : XfsComponent
    {
        public XfsAsyncUserToken? Token;
        public byte[]? Message;
    }

}
